# Monorepo Discipline: Turborepo, Boundaries, and CI lastEditedTime: 2025-10-05T15:57:00.000Z createdTime: 2025-10-05T14:39:00.000Z categories: ["Monorepo","Turborepo","Ci","Quality"] language: en description: Monorepo discipline with Turborepo: workspaces, cached pipelines, import boundaries, versioning with Changesets, and CI basics. slug: monorepo-best-practices-en image: [{"type":"external","name":"https://fastly.picsum.photos/id/623/2365/1774.jpg?hmac=3S6IawWTvvVdIB5p3UeUvipCtVVYrsGjzREy4opp1H4","external":{"url":"https://fastly.picsum.photos/id/623/2365/1774.jpg?hmac=3S6IawWTvvVdIB5p3UeUvipCtVVYrsGjzREy4opp1H4"}}] status: published ------------------------------------------- ### Goals - Fast builds, clear ownership, safe API boundaries ### 1) Workspaces - Use pnpm or yarn workspaces for deterministic installs - One package per purpose: apps/_, packages/_, tooling/* ### 2) Task pipelines - Turborepo with local and remote cache in CI - Consistent scripts: build, dev, test, lint, typecheck ### 3) Boundaries - ESLint rules and TS path mapping to enforce imports - No deep imports across packages. Re-export from index ### 4) Versioning and releases - Changesets for versions and changelogs - Publish only public packages. Keep internals private ### 5) Testing strategy - Unit tests isolated per package - E2E in apps and run against preview deployments ### 6) DX - Strict tsconfig.base.json at the root - Shared Prettier and ESLint in a tooling package ### Example: turbo.json ```json { "$schema": "https://turbo.build/schema.json", "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] }, "dev": { "cache": false }, "lint": { "outputs": [] }, "typecheck": { "outputs": [] }, "test": { "outputs": ["coverage/**"] } } } ``` ### Checklist - Cached pipelines - Strict boundaries and clear ownership